﻿package kliment.controls.mediaplayer.core.players {
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.media.ID3Info;
	import flash.media.Sound;
	import flash.media.SoundChannel;
	import flash.media.SoundLoaderContext;
	import flash.media.SoundTransform;
	import flash.net.URLRequest;
	import kliment.events.PlayerEvent;
	import kliment.math.Calc;
	import kliment.utils.IntervalTimer;
	
	
	/**
     * Dispatched when .....
     */
    [Event(name = 'id3', type = 'kliment.events.PlayerEvent')]
	
	/**
	 * ...
	 * @author	Kliment
	 * @version	0.1.4
	 * 
	 * class name: kliment.controls.mediaplayer.core.players.MP3Player
	 */
	public class MP3Player extends AbstractPlayer implements IPlayer{
		private static const _MILLISECONDS:Number = 1000;
		private var _sound:Sound;
		private var _soundChannel:SoundChannel;
		private var _id3:ID3Info;
		
		public function MP3Player() {
			_intervalTimer = new IntervalTimer(_updateInfo, UPDATE_DELAY, true, false);
		}
		
		private function _init():void {
			_sound = new Sound();
			
			_sound.addEventListener(Event.OPEN, _soundHandler);
			_sound.addEventListener(ProgressEvent.PROGRESS, _soundHandler);
			_sound.addEventListener(Event.ID3, _soundHandler);
			_sound.addEventListener(Event.COMPLETE, _soundHandler);
			_sound.addEventListener(IOErrorEvent.IO_ERROR, _soundHandler);
			//_sound.addEventListener(Event.SOUND_COMPLETE, _soundHandler); //don't stabel
		}
		
		private function _updateInfo():void {
			if (_sound && _soundChannel){
				var pos:Number = position;
				if (_state == PlayerEvent.PLAYING) {
					dispatchEvent(new PlayerEvent(PlayerEvent.PLAYING, false, false, _bytesLoaded, _bytesTotlal,  pos));
				}
				if ( pos > .9) {
					_intervalTimer.stop();
					_state = PlayerEvent.PLAY_COMPLETE;
					dispatchEvent(new PlayerEvent(PlayerEvent.PLAY_COMPLETE, false, false));
					return;
				}
			}
		}
		
		private function _soundHandler(event:Event):void {
			switch(event.type) {
				case Event.OPEN:
					_pausePosition = 0;
					
					_intervalTimer.start();
					dispatchEvent(new PlayerEvent(PlayerEvent.OPEN));
				break;
				
				case Event.ID3:
					_id3 = _sound.id3;
					dispatchEvent(new PlayerEvent(PlayerEvent.ID3));
				break;
				
				case ProgressEvent.PROGRESS:
					_bytesTotlal = _sound.bytesTotal;
					_bytesLoaded = _sound.bytesLoaded;
					dispatchEvent(new PlayerEvent(PlayerEvent.PROGRESS, false, false, _bytesLoaded, _bytesTotlal));
				break;
				
				case Event.SOUND_COMPLETE:
					dispatchEvent(new PlayerEvent(PlayerEvent.PLAY_COMPLETE));
				break;
				
				case IOErrorEvent.IO_ERROR:
					dispatchEvent(new PlayerEvent(PlayerEvent.IO_ERROR));
				break
				
				case Event.COMPLETE:
					_isLoaded = true;
					dispatchEvent(new PlayerEvent(PlayerEvent.COMPLETE));
				break;
			}
		}
		
		override public function load(url:String):void {
			remove();
			_init();
			_sound.load(new URLRequest(url)/*, new SoundLoaderContext()*/);
			super.load(url);
		}
		
		override public function play():void {
			if (!_sound && _url.length > 0) {
				load(_url);
			}
			_soundChannel = _sound.play(_pausePosition, 0, _soundTransform);
			_soundChannel.soundTransform = _soundTransform;
			super.play();
		}
		
		override public function pause():void {
			if (!_isLoaded) return;
			_pausePosition = _soundChannel.position;
			_soundChannel.stop();
			super.pause();
		}
		
		override public function stop():void {
			if (!_isLoaded) {
				_sound = null;
				_intervalTimer.stop()
			}
			_pausePosition = 0;
			_soundChannel.stop();
			super.stop()
		}
		
		override public function forward():void {
			if (!_isLoaded) return;
			_pausePosition = _soundChannel.position;
			_soundChannel.stop();
			_soundChannel = _sound.play(_pausePosition + STEP_SECONDS * _MILLISECONDS);
		}
		
		override public function back():void {
			if (!_isLoaded) return;
			_pausePosition = _soundChannel.position;
			_soundChannel.stop();
			_soundChannel = _sound.play(_pausePosition - STEP_SECONDS * _MILLISECONDS);
		}
		
		override public function get position():Number { return _soundChannel.position / _sound.length; }
		override public function set position(value:Number):void { 
			if (!_isLoaded) return;
			value = Calc.inInterval(0, 1, value);
			_soundChannel.stop();
			_sound.play(_sound.length * value);
		}
		
		override public function get time():Number { return _soundChannel.position; }
		
		override public function get duration():Number { return _sound.length; }
		
		public function get id3():ID3Info { return _id3; }
		
		override public function set soundTransform(value:SoundTransform):void {
			super.soundTransform = value;
			if (_soundChannel)
				_soundChannel.soundTransform = soundTransform;
		}
		
		override public function remove():void {
			if (_soundChannel)
				_soundChannel.stop();
			if (_sound) {
				try {_sound.close() } catch (e:Error) {  }
				_sound.removeEventListener(Event.OPEN, _soundHandler);
				_sound.removeEventListener(Event.ID3, _soundHandler);
				_sound.removeEventListener(ProgressEvent.PROGRESS, _soundHandler);
				_sound.removeEventListener(IOErrorEvent.IO_ERROR, _soundHandler);
				_sound = null;
			}
			_intervalTimer.stop();
			super.remove();
		}
	}

}